package com.mulong.mall.service.impl;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mulong.common.client.AliyunOssClient;
import com.mulong.common.dao.mall.ChannelDao;
import com.mulong.common.dao.mall.InventoryDao;
import com.mulong.common.dao.mall.ProductDao;
import com.mulong.common.dao.mall.SizeConversionDao;
import com.mulong.common.domain.pojo.mall.SupplierChannel;
import com.mulong.common.domain.pojo.mall.custom.DownloadInventory;
import com.mulong.common.domain.pojo.mall.custom.DownloadInventoryQuery;
import com.mulong.common.domain.pojo.mall.custom.ProductBarcodeQuery;
import com.mulong.common.domain.pojo.mall.custom.ProductInventoryProduct;
import com.mulong.common.domain.pojo.mall.custom.ProductQuery;
import com.mulong.common.domain.pojo.mall.custom.SizeConversionQuery;
import com.mulong.common.exception.ErrorEnums;
import com.mulong.common.exception.MulongException;
import com.mulong.common.util.MulongUtil;
import com.mulong.mall.constants.Constants;
import com.mulong.mall.domain.bo.ProductInventory;
import com.mulong.mall.domain.bo.manager.*;
import com.mulong.mall.domain.param.manager.*;
import com.mulong.mall.domain.result.manager.*;
import com.mulong.mall.service.ManagerGoodsService;
import com.mulong.mall.service.support.ManagerGoodsSupport;
import com.mulong.mall.util.MallRequestContext;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * ManagerGoodsServiceImpl
 * 
 * @author mulong
 * @data 2021-06-21 14:02:36
 */
@Slf4j
@Service
public class ManagerGoodsServiceImpl implements ManagerGoodsService {
    @Autowired
    private InventoryDao inventoryDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private SizeConversionDao sizeConversionDao;
    @Autowired
    private ChannelDao channelDao;
    @Autowired
    private ManagerGoodsSupport managerGoodsSupport;
    @Autowired
    private AliyunOssClient aliyunOssClient;

    /**
     * 上传库存
     * 
     * @author mulong
     */
    @Override
    public UploadInventoryResult uploadInventory(Integer supplierChannelId, MultipartFile file) {
        SupplierChannel supplierChannel = channelDao.queryById(supplierChannelId);
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.SUPPLIER_UPLOAD_INVENTORY_SHEET_NAME);
            List<com.mulong.common.domain.pojo.mall.Inventory> inventoryRecords = managerGoodsSupport.buildInventoryList(reader, supplierChannel);
            reader.close();
            if (!CollectionUtils.isEmpty(inventoryRecords)) {
                try {
                    inventoryDao.addAll(supplierChannel.getId(), inventoryRecords, 1000, MallRequestContext.getUsername());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format(e.getMessage()));
                }
            }
            UploadInventoryResult uploadInventoryResult = new UploadInventoryResult();
            uploadInventoryResult.setInventoryCount(inventoryRecords.size());
            return uploadInventoryResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

    /**
     * 下载库存导入模板
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadInventoryTemplate() {
        String fileName = Constants.MANAGER_UPLOAD_INVENTORY_TEMPLATE_FILENAME;
        String ossKey = Constants.MANAGER_UPLOAD_INVENTORY_TEMPLATE_OSS_KEY;
        byte[] content = null;
        try {
            content = aliyunOssClient.downloadToByteArray(ossKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("下载模板异常"));
        }
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 下载库存
     * 
     * @author mulong 
     */
    @Override
    public ResponseEntity<byte[]> downloadInventory(DownloadInventoryParam param) {
        List<Integer> supplierChannelIdList = param.getSupplierChannelIdList();
        if (CollectionUtils.isEmpty(supplierChannelIdList)) {
            throw new MulongException(ErrorEnums.ILLEGAL_LESS_PARAM_TEMPLETE.format("supplierChannelIdList"));
        }
        String fileName = Constants.MANAGER_DOWNLOAD_INVENTORY_FILENAME;
        // get data
        DownloadInventoryQuery downloadInventoryQuery = new DownloadInventoryQuery();
        downloadInventoryQuery.setSupplierChannelIdList(supplierChannelIdList);;
        downloadInventoryQuery.setOrderBy("i.`supplier_channel_id` ASC, i.`sku` ASC");
        List<DownloadInventory> productInventoryRecords = inventoryDao.queryDownloadInventory(downloadInventoryQuery);
        // build content
        byte[] content = null;
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet(Constants.MANAGER_DOWNLOAD_INVENTORY_SHEET_NAME);            
            List<String> titles = Constants.MANAGER_DOWNLOAD_INVENTORY_SHEET_TITLE;
            MulongUtil.addTitle(workbook, sheet, titles);
            HSSFCellStyle defaultStyle = MulongUtil.getDefaultCellStyle(workbook);
            int lastRowNum = sheet.getLastRowNum();
            for (int j = 0; j < productInventoryRecords.size(); j++) {
                DownloadInventory productInventoryRecord = productInventoryRecords.get(j);
                HSSFRow row = sheet.createRow(j + (lastRowNum + 1));
                managerGoodsSupport.addRow(row, productInventoryRecord, defaultStyle);
            }
            content = MulongUtil.toByteArray(workbook);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("导出数据异常"));
        }
        // build response
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 查询商品库存
     * 
     * @author mulong
     */
    @Override
    public GetProductInventoryResult getProductInventory(GetProductInventoryParam param) {
        String skuPrefix = param.getSkuPrefix();
        if (StringUtils.isBlank(skuPrefix) || skuPrefix.length() < 2) {
            throw new MulongException(ErrorEnums.ILLEGAL_FORMAT_PARAM_TEMPLETE.format("skuPrefix"));
        }
        List<ProductInventoryProduct> records = productDao.queryProductInventoryProductBySkuPrefix(skuPrefix);
        GetProductInventoryResult getProductInventoryResult = new GetProductInventoryResult();
        if (!CollectionUtils.isEmpty(records)) {
            List<ProductInventory> list = records.stream().map(ProductInventory::new).collect(Collectors.toList());
            getProductInventoryResult.setList(list);   
        }
        return getProductInventoryResult;
    }

    /**
     * 查询商品
     * 
     * @author mulong
     */
    @Override
    public GetProductByPageResult getProductByPage(GetProductByPageParam param) {
        ProductQuery query = new ProductQuery();
        query.setSku(param.getSku());
        query.setBrandId(param.getBrandId());
        query.setGoodsCategory(param.getGoodsCategory());
        query.setYear(param.getYear());
        query.setSeason(param.getSeason());
        query.setGoodsSex(param.getGoodsSex());
        query.setOrderBy("`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<com.mulong.common.domain.pojo.mall.Product> page = (Page<com.mulong.common.domain.pojo.mall.Product>) productDao.query(query);
        GetProductByPageResult getProductByPageResult = new GetProductByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<com.mulong.common.domain.pojo.mall.Product> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getProductByPageResult.setResult(list.stream().map(Product::new).collect(Collectors.toList()));
        }
        return getProductByPageResult;
    }

    /**
     * 添加商品
     * 
     * @author mulong 
     */
    @Override
    public Product addProduct(Product product) {
        product.setId(null);
        com.mulong.common.domain.pojo.mall.Product newRecord = product.buildProduct();
        newRecord = productDao.add(newRecord, MallRequestContext.getUsername());
        return new Product(newRecord);
    }

    /**
     * 查询商品
     * 
     * @author mulong 
     */
    @Override
    public Product getProductById(Long id) {
        com.mulong.common.domain.pojo.mall.Product record = productDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new Product(record);
    }

    /**
     * 更新商品
     * 
     * @author mulong 
     */
    @Override
    public Product putProductById(Long id, Product product) {
        if (!id.equals(product.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.Product record = productDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.Product newRecord = product.buildProduct();
        record.setSku(newRecord.getSku());
        record.setBrandId(newRecord.getBrandId());
        record.setName(newRecord.getName());
        record.setSeries(newRecord.getSeries());
        record.setGoodsCategory(newRecord.getGoodsCategory());
        record.setYear(newRecord.getYear());
        record.setSeason(newRecord.getSeason());
        record.setGoodsSex(newRecord.getGoodsSex());
        record.setColor(newRecord.getColor());
        record.setWeight(newRecord.getWeight());
        record.setMarketPrice(newRecord.getMarketPrice());
        record.setSaleProps(newRecord.getSaleProps());
        record.setMaterial(newRecord.getMaterial());
        record.setRemark(newRecord.getRemark());
        productDao.put(record, MallRequestContext.getUsername());
        return new Product(record);
    }

    /**
     * 删除商品
     * 
     * @author mulong 
     */
    @Override
    public Product deleteProductById(Long id) {
        com.mulong.common.domain.pojo.mall.Product record = productDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        productDao.delete(record, MallRequestContext.getUsername());
        return new Product(record);
    }

    /**
     * 下载商品
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadProduct(DownloadProductParam param) {
        String fileName = Constants.MANAGER_DOWNLOAD_PRODUCT_FILENAME;
        // get data
        ProductQuery query = new ProductQuery();
        query.setSku(param.getSku());
        query.setBrandId(param.getBrandId());
        query.setGoodsCategory(param.getGoodsCategory());
        query.setYear(param.getYear());
        query.setSeason(param.getSeason());
        query.setGoodsSex(param.getGoodsSex());
        List<com.mulong.common.domain.pojo.mall.custom.CustomProduct> records = productDao.queryCustom(query);
        // build content
        byte[] content = null;
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet(Constants.MANAGER_DOWNLOAD_PRODUCT_SHEET_NAME);            
            List<String> titles = Constants.MANAGER_DOWNLOAD_PRODUCT_SHEET_TITLE;
            MulongUtil.addTitle(workbook, sheet, titles);
            HSSFCellStyle defaultStyle = MulongUtil.getDefaultCellStyle(workbook);
            int lastRowNum = sheet.getLastRowNum();
            for (int j = 0; j < records.size(); j++) {
                com.mulong.common.domain.pojo.mall.custom.CustomProduct record = records.get(j);
                HSSFRow row = sheet.createRow(j + (lastRowNum + 1));
                managerGoodsSupport.addRow(row, record, defaultStyle);
            }
            content = MulongUtil.toByteArray(workbook);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("导出数据异常"));
        }
        // build response
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 上传商品
     * 
     * @author mulong
     */
    @Override
    public UploadProductResult uploadProduct(MultipartFile file) {
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.MANAGER_UPLOAD_PRODUCT_SHEET_NAME);
            List<UploadProductRecord> records = managerGoodsSupport.buildUploadProductRecordList(reader);
            reader.close();
            if (!CollectionUtils.isEmpty(records)) {
                managerGoodsSupport.insertProduct(records);
            }
            UploadProductResult uploadProductResult = new UploadProductResult();
            uploadProductResult.setProductCount(records.size());
            return uploadProductResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

    /**
     * 下载产品信息模板
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadProductTemplate() {
        String fileName = Constants.MANAGER_UPLOAD_PRODUCT_TEMPLATE_FILENAME;
        String ossKey = Constants.MANAGER_UPLOAD_PRODUCT_TEMPLATE_OSS_KEY;
        byte[] content = null;
        try {
            content = aliyunOssClient.downloadToByteArray(ossKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("下载模板异常"));
        }
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 查询尺码
     * 
     * @author mulong
     */
    @Override
    public GetSizeConversionByPageResult getSizeByPage(GetSizeConversionByPageParam param) {
        SizeConversionQuery query = new SizeConversionQuery();
        query.setBrandId(param.getBrandId());
        query.setGoodsCategory(param.getGoodsCategory());
        query.setGoodsSex(param.getGoodsSex());
        query.setOrderBy("`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<com.mulong.common.domain.pojo.mall.SizeConversion> page = (Page<com.mulong.common.domain.pojo.mall.SizeConversion>) sizeConversionDao.query(query);
        GetSizeConversionByPageResult getSizeConversionByPageResult = new GetSizeConversionByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<com.mulong.common.domain.pojo.mall.SizeConversion> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getSizeConversionByPageResult.setResult(list.stream().map(SizeConversion::new).collect(Collectors.toList()));
        }
        return getSizeConversionByPageResult;
    }

    /**
     * 添加尺码
     * 
     * @author mulong 
     */
    @Override
    public SizeConversion addSize(SizeConversion sizeConversion) {
        sizeConversion.setId(null);
        com.mulong.common.domain.pojo.mall.SizeConversion newRecord = sizeConversion.buildSizeConversion();
        newRecord = sizeConversionDao.add(newRecord, MallRequestContext.getUsername());
        return new SizeConversion(newRecord);
    }

    /**
     * 查询尺码
     * 
     * @author mulong 
     */
    @Override
    public SizeConversion getSizeById(Integer id) {
        com.mulong.common.domain.pojo.mall.SizeConversion record = sizeConversionDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new SizeConversion(record);
    }

    /**
     * 更新尺码
     * 
     * @author mulong 
     */
    @Override
    public SizeConversion putSizeById(Integer id, SizeConversion sizeConversion) {
        if (!id.equals(sizeConversion.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.SizeConversion record = sizeConversionDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.SizeConversion newRecord = sizeConversion.buildSizeConversion();
        record.setBrandId(newRecord.getBrandId());
        record.setGoodsCategory(newRecord.getGoodsCategory());
        record.setGoodsSex(newRecord.getGoodsSex());
        record.setOriginalSize(newRecord.getOriginalSize());
        record.setNormalizedSize(newRecord.getNormalizedSize());
        record.setRemark(newRecord.getRemark());
        sizeConversionDao.put(record, MallRequestContext.getUsername());
        return new SizeConversion(record);
    }

    /**
     * 删除尺码
     * 
     * @author mulong 
     */
    @Override
    public SizeConversion deleteSizeById(Integer id) {
        com.mulong.common.domain.pojo.mall.SizeConversion record = sizeConversionDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        sizeConversionDao.delete(record, MallRequestContext.getUsername());
        return new SizeConversion(record);
    }

    /**
     * 下载尺码
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadSize(DownloadSizeConversionParam param) {
        String fileName = Constants.MANAGER_DOWNLOAD_SIZE_CONVERSION_FILENAME;
        // get data
        SizeConversionQuery query = new SizeConversionQuery();
        query.setBrandId(param.getBrandId());
        query.setGoodsCategory(param.getGoodsCategory());
        query.setGoodsSex(param.getGoodsSex());
        query.setOrderBy("sc.`update_time` DESC");
        List<com.mulong.common.domain.pojo.mall.custom.CustomSizeConversion> records = sizeConversionDao.queryCustom(query);
        // build content
        byte[] content = null;
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet(Constants.MANAGER_DOWNLOAD_SIZE_CONVERSION_SHEET_NAME);            
            List<String> titles = Constants.MANAGER_DOWNLOAD_SIZE_CONVERSION_SHEET_TITLE;
            MulongUtil.addTitle(workbook, sheet, titles);
            HSSFCellStyle defaultStyle = MulongUtil.getDefaultCellStyle(workbook);
            int lastRowNum = sheet.getLastRowNum();
            for (int j = 0; j < records.size(); j++) {
                com.mulong.common.domain.pojo.mall.custom.CustomSizeConversion record = records.get(j);
                HSSFRow row = sheet.createRow(j + (lastRowNum + 1));
                managerGoodsSupport.addRow(row, record, defaultStyle);
            }
            content = MulongUtil.toByteArray(workbook);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("导出数据异常"));
        }
        // build response
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 上传尺码
     * 
     * @author mulong
     */
    @Override
    public UploadSizeResult uploadSize(MultipartFile file) {
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.MANAGER_UPLOAD_SIZE_CONVERSION_SHEET_NAME);
            List<UploadSizeConversionRecord> records = managerGoodsSupport.buildUploadSizeConversionRecordList(reader);
            reader.close();
            if (!CollectionUtils.isEmpty(records)) {
                managerGoodsSupport.insertSizeConversion(records);
            }
            UploadSizeResult uploadSizeResult = new UploadSizeResult();
            uploadSizeResult.setSizeCount(records.size());
            return uploadSizeResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

    /**
     * 下载尺码转换模板
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadSizeTemplate() {
        String fileName = Constants.MANAGER_UPLOAD_SIZE_CONVERSION_TEMPLATE_FILENAME;
        String ossKey = Constants.MANAGER_UPLOAD_SIZE_CONVERSION_TEMPLATE_OSS_KEY;
        byte[] content = null;
        try {
            content = aliyunOssClient.downloadToByteArray(ossKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("下载模板异常"));
        }
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 查询条形码
     * 
     * @author mulong
     */
    @Override
    public GetBarcodeByPageResult getBarcodeByPage(GetBarcodeByPageParam param) {
        ProductBarcodeQuery query = new ProductBarcodeQuery();
        query.setSku(param.getSku());
        query.setBarcode(param.getBarcode());
        query.setOrderBy("`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<com.mulong.common.domain.pojo.mall.ProductBarcode> page = (Page<com.mulong.common.domain.pojo.mall.ProductBarcode>) productDao.queryBarcode(query);
        GetBarcodeByPageResult getBarcodeByPageResult = new GetBarcodeByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<com.mulong.common.domain.pojo.mall.ProductBarcode> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getBarcodeByPageResult.setResult(list.stream().map(Barcode::new).collect(Collectors.toList()));
        }
        return getBarcodeByPageResult;
    }

    /**
     * 添加条形码
     * 
     * @author mulong 
     */
    @Override
    public Barcode addBarcode(Barcode barcode) {
        barcode.setId(null);
        com.mulong.common.domain.pojo.mall.ProductBarcode newRecord = barcode.buildProductBarcode();
        newRecord = productDao.addBarcode(newRecord, MallRequestContext.getUsername());
        return new Barcode(newRecord);
    }

    /**
     * 查询条形码
     * 
     * @author mulong 
     */
    @Override
    public Barcode getBarcodeById(Long id) {
        com.mulong.common.domain.pojo.mall.ProductBarcode record = productDao.queryBarcodeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new Barcode(record);
    }

    /**
     * 更新条形码
     * 
     * @author mulong 
     */
    @Override
    public Barcode putBarcodeById(Long id, Barcode barcode) {
        if (!id.equals(barcode.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.ProductBarcode record = productDao.queryBarcodeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.ProductBarcode newRecord = barcode.buildProductBarcode();
        record.setSku(newRecord.getSku());
        record.setNormalizedSize(newRecord.getNormalizedSize());
        record.setBarcode(newRecord.getBarcode());
        productDao.putBarcode(record, MallRequestContext.getUsername());
        return new Barcode(record);
    }

    /**
     * 删除条形码
     * 
     * @author mulong 
     */
    @Override
    public Barcode deleteBarcodeById(Long id) {
        com.mulong.common.domain.pojo.mall.ProductBarcode record = productDao.queryBarcodeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        productDao.deleteBarcode(record, MallRequestContext.getUsername());
        return new Barcode(record);
    }

    /**
     * 下载条形码
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadBarcode(DownloadBarcodeParam param) {
        String fileName = Constants.MANAGER_DOWNLOAD_BARCODE_FILENAME;
        // get data
        ProductBarcodeQuery query = new ProductBarcodeQuery();
        query.setSku(param.getSku());
        query.setBarcode(param.getBarcode());
        query.setOrderBy("`update_time` DESC");
        List<com.mulong.common.domain.pojo.mall.ProductBarcode> records = productDao.queryBarcode(query);
        // build content
        byte[] content = null;
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet(Constants.MANAGER_DOWNLOAD_BARCODE_SHEET_NAME);            
            List<String> titles = Constants.MANAGER_DOWNLOAD_BARCODE_SHEET_TITLE;
            MulongUtil.addTitle(workbook, sheet, titles);
            HSSFCellStyle defaultStyle = MulongUtil.getDefaultCellStyle(workbook);
            int lastRowNum = sheet.getLastRowNum();
            for (int j = 0; j < records.size(); j++) {
                com.mulong.common.domain.pojo.mall.ProductBarcode record = records.get(j);
                HSSFRow row = sheet.createRow(j + (lastRowNum + 1));
                managerGoodsSupport.addRow(row, record, defaultStyle);
            }
            content = MulongUtil.toByteArray(workbook);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("导出数据异常"));
        }
        // build response
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 上传条形码
     * 
     * @author mulong
     */
    @Override
    public UploadBarcodeResult uploadBarcode(MultipartFile file) {
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.MANAGER_UPLOAD_BARCODE_SHEET_NAME);
            List<UploadBarcodeRecord> records = managerGoodsSupport.buildUploadBarcodeRecordList(reader);
            reader.close();
            if (!CollectionUtils.isEmpty(records)) {
                managerGoodsSupport.insertBarcode(records);
            }
            UploadBarcodeResult uploadBarcodeResult = new UploadBarcodeResult();
            uploadBarcodeResult.setBarcodeCount(records.size());
            return uploadBarcodeResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

    /**
     * 下载条形码信息模板
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadBarcodeTemplate() {
        String fileName = Constants.MANAGER_UPLOAD_BARCODE_TEMPLATE_FILENAME;
        String ossKey = Constants.MANAGER_UPLOAD_BARCODE_TEMPLATE_OSS_KEY;
        byte[] content = null;
        try {
            content = aliyunOssClient.downloadToByteArray(ossKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("下载模板异常"));
        }
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

}
